package pqsk.android.audio.ViewModels;

import gueei.binding.Command;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import pqsk.android.audio.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Toast;

public class vmAudioMixer
{
	Activity context;
	View activeView;
	public Command CmdSendSignal = new Command()
	{
		public void Invoke(View arg0,Object...arg1)
		{
			activeView = arg0;
			sendSignal();
		}
	};
	public Command CmdBeginDelayedAudio = new Command()
	{
		public void Invoke(View arg0,Object...arg1)
		{
			activeView = arg0;
			BeginDelayedAudio();
		}
	};
	public vmAudioMixer(Activity context)
	{
		this.context = context;
	}
	private String GetIPAddress()
	{
		WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
		 WifiInfo wifiInfo = wifiManager.getConnectionInfo();		 
		 int ip = wifiInfo.getIpAddress();
		 String strIP = String.format( 
				    "%d.%d.%d.%d", 
				    (ip & 0xff), 
				    (ip >> 8 & 0xff),
				    (ip >> 16 & 0xff),
				    (ip >> 24 & 0xff));
		 return strIP;
	}
		
	private boolean isUsingDelayedAudio;
	private String strDelayType;
	private long lDelay;
	private String strRingtonePreference;
	private Uri uriSound;
	private boolean isVibrating;
	private long lTime;
	private void GetSettings()
	{
		SharedPreferences settings = PreferenceManager
		        .getDefaultSharedPreferences(this.context.getBaseContext()); // zero is the
																// default
//		Map<String, ?> mAll = settings.getAll();
//		if (mAll != null && mAll.size() > 0)
//		{
//			for (Map.Entry<String, ?> entry : mAll.entrySet())
//			{
//				String strMsg = entry.getKey() + "/" + entry.getValue();
//				this.alert(strMsg);
//				Toast.makeText(this, strMsg, Toast.LENGTH_LONG).show();
//			}
//		}
		this.isUsingDelayedAudio = settings.getBoolean("chkSignal", false); // false
																			   // is
																			   // the
																			   // default
		lTime = 1000;//defaults to seconds
		this.strDelayType = settings.getString("Time", "s");
		//todo: add enums or resources to define types
		if (this.strDelayType.contains("m"))
		{
			lTime = 1000 * 60;
		} else if (this.strDelayType.contains("h"))
		{
			lTime = (1000 * 60) * 60;
		}
		
		this.lDelay = settings.getInt("seekDelay", 60);//default to 60.....default time is seconds
		// boolean
		this.strRingtonePreference = settings.getString("DefaultDelayedAudio", "DEFAULT_RINGTONE_URI");
		this.uriSound = Uri.parse(this.strRingtonePreference);
		this.isVibrating = settings.getBoolean("chkVibrate", true);
	}
	
	public void BeginDelayedAudio()
	{
		this.GetSettings();		
		final Uri uriSoundSetting = this.uriSound;
		final boolean isVibratingSettingEnabled = this.isVibrating;
		this.Notify(this.lDelay, this.strDelayType.contains("s") ? "second" : this.strDelayType.contains("m") ? "minute" : "hour");
		if(this.isUsingDelayedAudio)
		{
			myTimer = new Timer();
			myTimer.schedule(new TimerTask()
			{
				@Override
				public void run()
				{
					playAudio(uriSoundSetting, isVibratingSettingEnabled);
				}

			}, this.lDelay * this.lTime);
		}//if
		else
		{
			//todo: wait for signal
		}
	}//beginDelayedAudio
	private NotificationManager mNotificationManager;
	private static final int HELLO_ID = 1;
	private void Notify(long lDelay, String strTime)
	{
		String strMsg = lDelay == -1
				? "The audio will begin when a signal is received"
				: "The delay will begin in " + lDelay + " " + strTime + "(s).";
		Toast.makeText(this.context, strMsg, Toast.LENGTH_LONG).show();
		// Get a reference to the NotificationManager:
		String ns = Context.NOTIFICATION_SERVICE;
		this.mNotificationManager = (NotificationManager) this.context.getSystemService(ns);

		// Instantiate the Notification:

		int icon = R.drawable.ic_launcher;
		CharSequence tickerText = "AudioMixer";
		long when = System.currentTimeMillis();

		Notification notification = new Notification(icon, tickerText, when);

		// Define the notification's message and PendingIntent:

		Context currentContext = this.context.getApplicationContext();
		CharSequence contentTitle = "AudioMixer";
		CharSequence contentText = strMsg;
		Intent notificationIntent = new Intent(currentContext, currentContext.getClass());
		PendingIntent contentIntent = PendingIntent.getActivity(currentContext, 0,
		        notificationIntent, 0);

		notification.setLatestEventInfo(currentContext, contentTitle, contentText,
		        contentIntent);

		// Pass the Notification to the NotificationManager:

		mNotificationManager.notify(HELLO_ID, notification);
		
		// That's it. Your user has now been notified.
	}
	
	private void alert(String strMsg)
	{
		AlertDialog.Builder alertbox = new AlertDialog.Builder(this.context);

		// Set the message to display
		alertbox.setMessage(strMsg);

		// Add a neutral button to the alert box and assign a click listener
		// alertbox.setNeutralButton("Ok", new DialogInterface.OnClickListener()
		// {
		//
		// // Click listener on the neutral button of alert box
		// public void onClick(DialogInterface arg0, int arg1) {
		//
		// // The neutral button was clicked
		// Toast.makeText(getApplicationContext(), strMsg,
		// Toast.LENGTH_LONG).show();
		// }
		// });
		alertbox.setNeutralButton("Ok", null);

		// show the alert box
		alertbox.show();
	}

	private Timer myTimer;
	
	private Vibrator vib;
	private void vibrate(long iDuration)
	{
		
		vib = (Vibrator) this.context.getSystemService(Context.VIBRATOR_SERVICE);
		

		// 1. Vibrate for 1000 milliseconds
		//long milliseconds = 1500;
		vib.vibrate(iDuration);

		// 2. Vibrate in a Pattern with 500ms on, 500ms off for 5 times
//		long[] pattern =
//			{ 500, 300 };
//		vib.vibrate(pattern, 5);
	}// vibrate()

	private final void playAudio(Uri uriSound, boolean isVibrating)
	{
		// This method is called directly by the timer
		// and runs in the same thread as the timer.

		// We call the method that will work with the UI
		// through the runOnUiThread method.
		this.context.runOnUiThread(Timer_Tick);
		
		// this case, R.raw.slayer represents an audio file called slayer.mp3
		// that is stored in the res/raw/ folder and once you click the button
		// the droid will rock you...
		// MediaPlayer mp = MediaPlayer.create( CheckbookActivity.this,
		// R.raw.slayer);
		// mp.start();
		//Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); 
		 MediaPlayer mMediaPlayer = new MediaPlayer();
		 try
       {
	        mMediaPlayer.setDataSource(this.context, uriSound);
       } catch (IllegalArgumentException e)
       {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
       } catch (SecurityException e)
       {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
       } catch (IllegalStateException e)
       {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
       } catch (IOException e)
       {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
       }
		 final AudioManager audioManager = (AudioManager)this.context.getSystemService(Context.AUDIO_SERVICE);
		 if (uriSound != null && audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
			 mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			 mMediaPlayer.setLooping(false);
			 try
           {
	            mMediaPlayer.prepare();
           } catch (IllegalStateException e)
           {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
           } catch (IOException e)
           {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
           }			 
			 mMediaPlayer.start();
			 if(mMediaPlayer.isPlaying())
			 {
				 if(isVibrating)
				 {
					 this.vibrate(mMediaPlayer.getDuration());
				 }//if
				 this.mNotificationManager.cancelAll();
			 }//if
		  }
	}

	private Runnable Timer_Tick = new Runnable()
	{
		public void run()
		{

			// This method runs in the same thread as the UI.

			// Do something to the UI thread here

		}
	};

	private void toast(String msg, long lInterval)
	{
		final Toast tag = Toast.makeText(this.context, msg,
		        Toast.LENGTH_LONG);

		tag.show();
		
		if(lInterval != 0)
		{		
			new CountDownTimer(lInterval, 1000)
			{	
				public void onTick(long millisUntilFinished)
				{
					tag.show();
				}
	
				public void onFinish()
				{
					tag.show();
				}
	
			}.start();
		}//if
	}
	
	private static final int PORT = 8080;
	Handler mHandler = new Handler();
	public void sendSignal()
	{
		ConnectivityManager connManager = (ConnectivityManager) this.context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		// Handler gets created on the UI-thread
	    
		if (mWifi.isConnected())
		{
			this.GetSettings();
			Thread t = null;
	
		    if(this.isUsingDelayedAudio)
		    {
				t = new Thread(new Runnable()
				{
					private BufferedReader reader = null;
					public void run()
					{
						Socket socket = null;
						ServerSocket server = null;
						try
						{
							server = new ServerSocket(vmAudioMixer.PORT);
							server.setReuseAddress(false);
							socket = server.accept();
				
						    this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
						    
						    final String line = reader.readLine();
						    mHandler.post(new Runnable()
						    {
						    	public void run()
						    	{
						    		alert("Signal received.\r\nResponse: " + line);
						    	}
						    });
						}//try
						catch(IOException ex)
						{							
							final String line = ex.getMessage();
						    mHandler.post(new Runnable()
						    {
						    	public void run()
						    	{
						    		alert("Error: " + line);
						    	}
						    });
						}//catch
						finally
						{
							try
							{
								if(server != null && reader != null)
								{
									server.close();
									reader.close();
								}//if
							}//try
							catch(Exception ex)
							{
								
							}//catch
						}//finally
					}//run
				});
		    }//if
		    else
		    {
				t = new Thread(new Runnable()
				{
					private BufferedWriter writer = null;
					Socket socket = null;
					public void run()
					{
						String ip = GetIPAddress();

						ip = ip.substring(0, ip.lastIndexOf("."));

				    	for(int i = 1 ; i < 255; i ++)
				    	{
				    		String host = ip + "." + i;
				    		try
				    		{	    			
				    			socket = new Socket(host,vmAudioMixer.PORT);
				    			
				    			final String line = host;
							    mHandler.post(new Runnable()
							    {
							    	public void run()
							    	{
							    		alert("Socket connected on " + line);
							    	}
							    });
				    			break;
				    			
				    		}//try
				    		catch(IOException ex)
				    		{				    			
				    			final String line = host;
							    mHandler.post(new Runnable()
							    {
							    	public void run()
							    	{
							    		toast("Connection to " + line + " was unsuccessful.",0);
							    	}
							    });
				    		}//ex
				    	}
				    	
				    	try
				    	{
				    		if(socket != null)
				    		{
				    			this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
						    	writer.write("I have connected to your phone.");
						    	writer.flush();
						    	mHandler.post(new Runnable()
							    {
							    	public void run()
							    	{
							    		toast("success", 0);
							    	}
							    });
				    		}//if
				    		else
				    		{
							    mHandler.post(new Runnable()
							    {
							    	public void run()
							    	{
							    		alert("unable to connect");
							    	}
							    });
				    			
				    		}
				    	}//try
				    	catch(IOException ex)
				    	{
				    		final String message = ex.getMessage();
				    		mHandler.post(new Runnable()
						    {
						    	public void run()
						    	{
						    		alert("error: " + message);
						    	}
						    });
				    		
				    	}//catch
				    	finally
				    	{
				    		if(writer != null && socket != null)
				    		{
				    			try
				    			{
				    				socket.close();
					    			writer.close();
				    			}//try
				    			catch(Exception ex)
				    			{
				    				
				    			}//catch
				    		}
				    	}//finally
					}
				});
		    }//else
			if(t != null)
			{
				t.setDaemon(true);
				t.start();
			}
		}//if
		else
		{
			this.alert("Wifi is not connected. Unable to send test signal");
		}//else
	}
}
